﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using HWEngine;
using HWEngine.Configuration;
using HWEngine.Generators;

namespace HandWriter
{
	public partial class FontEditorDialog : Form
	{
		public LetterSet LetterSet { get; private set; }
		private bool _fontsLoaded = false;
		private string _buffer = string.Empty;

		public FontEditorDialog(LetterSet set)
		{
			LetterSet = set;
			InitializeComponent();

			edFontName.Text = set.FontName;

			cmbSystemFonts.DataSource = Program.FontNames;

			var selected = Program.FontNames.FirstOrDefault(f => set.SystemFontMatchName == f);
			if (!string.IsNullOrEmpty(selected))
			{
				cmbSystemFonts.SelectedItem = selected;
			}

			int i = cmbSystemFonts.SelectedIndex;
			bool allOk = false;
			while (!allOk)
			{
				allOk = true;
				try
				{
					edTextPreview.Font = new Font(cmbSystemFonts.Items[i].ToString(), 10);
				}
				catch (Exception)
				{
					allOk = false;
					++i;
				}
			}
			cmbSystemFonts.SelectedIndex = i;

			LoadLettersListView();

			RenderTextSample();
			
			_fontsLoaded = true;
		}

		private void FontEditor_Load(object sender, EventArgs e)
		{
			
		}

		private void UpdateLetterInTreeView(Letter letter, bool exists)
		{
			ListViewItem resultItem = null;
			if (exists)
			{
				foreach (ListViewItem item in lvLetters.Items)
				{
					var let = item.Tag as Letter;
					if (let != null && let.Equals(letter))
					{
						resultItem = item;
						break;
					}
				}
			}
			else
			{
				resultItem = AddItemToLettersTree(letter);
			}
			resultItem.Text = letter.Caption;
			if (letter.ChangedLines || !exists)
			{
				imagelistLetters.Images.Add(GenerateLetterImage(letter, new Size(48, 48)));
				resultItem.ImageIndex = imagelistLetters.Images.Count - 1;
				letter.ChangedLines = false;
			}

			RenderTextSample();
			RenderBigLetterSample();
		}

		private static Image GenerateLetterImage(Letter letter, Size size)
		{
			var b = new Bitmap(size.Width, size.Height);
			Bitmap im = Image.FromHbitmap(b.GetHbitmap());
			using (Graphics g = Graphics.FromImage(im))
			{
				g.Clear(Color.White);
				g.SmoothingMode = SmoothingMode.HighQuality;
				letter.SetColor(Color.Black);
				letter.SetLineWidth(1.7f);
				letter.SetScale(size.Width / 2, size.Height / 2);
				letter.SetShift(size.Width / 4, size.Height / 4);
				letter.Draw(g);
				letter.SetShift(0f, 0f);
				letter.SetScale(1f, 1f);
			}
			return im;
		}

		private ListViewItem AddItemToLettersTree(Letter letter)
		{
			ListViewItem item = lvLetters.Items.Add(letter.Caption);
			item.Tag = letter;
			lvLetters.SelectedItems.Clear();
			return item;
		}

		public void LoadLettersListView()
		{
			lvLetters.BeginUpdate();
			imagelistLetters.Images.Clear();
			lvLetters.Items.Clear();
			int i = 0;
			foreach (Letter l in LetterSet.GetLetters())
			{
				imagelistLetters.Images.Add(GenerateLetterImage(l, new Size(48, 48)));
				ListViewItem item = AddItemToLettersTree(l);
				item.ImageIndex = i;
				i++;
			}
			lvLetters.EndUpdate();
		}

		public void ClickSelectedLetterItem()
		{
			//edit letter
			if (lvLetters.SelectedItems.Count > 0)
			{
				using (var f = new LetterEditorDialog())
				{
					var l = lvLetters.SelectedItems[0].Tag as Letter;
					string oldKey = l.Key;
					f.LoadData(l);
					f.ShowDialog();

					if (oldKey != l.Key)
					{
						LetterSet.Remove(l);
						LetterSet.Add(l);
					}

					UpdateLetterInTreeView(l, true);
				}
			}
		}

		private void listView1_DoubleClick(object sender, EventArgs e)
		{
			ClickSelectedLetterItem();
		}

		private void btnAddLetter_Click(object sender, EventArgs e)
		{
			//new letter
			var l = new Letter { Key = "A", Width = 50 };
			LetterSet.Add(l);
			UpdateLetterInTreeView(l, false);
		}

		private void btnCopyLetter_click(object sender, EventArgs e)
		{
			//copy letter
			if (lvLetters.SelectedItems.Count > 0)
			{
				var l = (Letter)lvLetters.SelectedItems[0].Tag;
				_buffer = Serializer.Serialize(l);
			}
		}

		private void btnPasteLetter_Click(object sender, EventArgs e)
		{
			if (!string.IsNullOrEmpty(_buffer))
			{
				var l2 = Serializer.Deserialize<Letter>(_buffer);
				LetterSet.Add(l2);
				UpdateLetterInTreeView(l2, false);
			}
		}

		private void btnDeleteLetter_Click(object sender, EventArgs e)
		{
			//delete letter
			if (MessageBox.Show("Do you really want to delete letter?", "Hand Writer", MessageBoxButtons.YesNo) == DialogResult.Yes)
			{
				if (lvLetters.SelectedItems.Count > 0)
				{
					var l = lvLetters.SelectedItems[0].Tag as Letter;
					LetterSet.Remove(l);
					lvLetters.Items.Remove(lvLetters.SelectedItems[0]);
				}
			}
		}

		private void btnSetTileView_Click(object sender, EventArgs e)
		{
			lvLetters.View = View.Tile;
			//this is a issue: when first change view happens, list view is not correct: all items placed in one column.
			lvLetters.View = View.LargeIcon;
			lvLetters.View = View.Tile;
		}

		private void btnSetLargeIcons_Click(object sender, EventArgs e)
		{
			lvLetters.View = View.LargeIcon;
		}

		private void btnRefresh_Click(object sender, EventArgs e)
		{
			LoadLettersListView();
		}

		private void lvLetters_SelectedIndexChanged(object sender, EventArgs e)
		{
			RenderBigLetterSample();
		}

		private void FontEditor_FormClosed(object sender, FormClosedEventArgs e)
		{
			
		}

		private void FontEditor_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (string.IsNullOrEmpty(edFontName.Text))
			{
				MessageBox.Show("Font name should be specified");
				e.Cancel = true;
			}

			LetterSet.FontName = edFontName.Text;
			LetterSet.SystemFontMatchName = cmbSystemFonts.SelectedItem.ToString();
		}

		private void cmbSystemFonts_SelectedValueChanged(object sender, EventArgs e)
		{
			bool isOk = false;
			if (_fontsLoaded)
			{
				try
				{
					edTextPreview.Font = new Font(cmbSystemFonts.SelectedItem.ToString(), 10);
					isOk = true;
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.Message);
					isOk = false;
				}
				if (isOk)
				{
					LetterSet.SystemFontMatchName = edTextPreview.Font.Name;
				}
			}
		}

		private void edTextInput_TextChanged(object sender, EventArgs e)
		{
			RenderTextSample();
		}

		private void RenderBigLetterSample()
		{
			// Generate a big image for selected letter and draw it
			if (lvLetters.SelectedItems.Count > 0)
			{
				Letter l = (Letter) lvLetters.SelectedItems[0].Tag;
				imgBigLetter.Image = GenerateLetterImage(l, imgBigLetter.Bounds.Size);

				lbCodeInfo.Text = l.Key.Length > 1 ? string.Empty : "Code: " + (int)l.Key[0];
				lbSymbolInfo.Text = "Symbol: " + l.Key;
				lbLinesCountInfo.Text = "Lines Count: " + l.Lines.Count;
				lbPointsCountInfo.Text = "Points Count: " + l.Lines.Aggregate(0, (count, next) => count + next.Points.Count);
			}
			else
			{
				imgBigLetter.Image = new Bitmap(imgBigLetter.Width, imgBigLetter.Height);
				lbCodeInfo.Text = string.Empty;
				lbSymbolInfo.Text = string.Empty;
				lbLinesCountInfo.Text = string.Empty;
				lbPointsCountInfo.Text = string.Empty;
			}
		}

		private void RenderTextSample()
		{
			var fakeRepository = new LetterSetRepository(LetterSet);
			HWGenerator hwgen = new HWGenerator(fakeRepository, new RectangleF(8, 8, picTextPreview.Width - 16, picTextPreview.Height - 16));

			var b = new Bitmap(picTextPreview.Width, picTextPreview.Height);
			Bitmap im = Image.FromHbitmap(b.GetHbitmap());
			using (Graphics g = Graphics.FromImage(im))
			{
				g.Clear(Color.White);
				g.SmoothingMode = SmoothingMode.HighQuality;
				hwgen.SimpleGenerate(w => w.Draw(g), edTextPreview.Text, edTextPreview.Font.Name, 20, Color.Black, 1.3f);
			}
			picTextPreview.Image = im;
		}

		private void edFontName_Leave(object sender, EventArgs e)
		{
			
		}

		private void edFontName_TextChanged(object sender, EventArgs e)
		{
			LetterSet.FontName = edFontName.Text;
		}

		
	}
}
